package sys;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;

public class ResourceLoader {
	private static ArrayList<ResourceLocation> locations = new ArrayList<ResourceLocation>();

	static {
		locations.add(new ClasspathLocation());
		locations.add(new FileSystemLocation(new File(".")));
	}

	public static InputStream getResourceAsStream(String ref) {
		InputStream in = null;

		for (int i = 0; i < locations.size(); i++) {
			ResourceLocation location = (ResourceLocation) locations.get(i);
			in = location.getResourceAsStream(ref);
			if (in != null) {
				break;
			}
		}

		if (in == null) {
			throw new RuntimeException("Resource not found: " + ref);
		}

		return new BufferedInputStream(in);
	}

	public static URL getResourceAsURL(String ref) {

		URL url = null;

		for (int i = 0; i < locations.size(); i++) {
			ResourceLocation location = (ResourceLocation) locations.get(i);
			url = location.getResourceAsURL(ref);
			if (url != null) {
				break;
			}
		}

		if (url == null) {
			throw new RuntimeException("Resource not found: " + ref);
		}

		return url;
	}

	public static boolean resourceExists(String ref) {
		URL url = null;

		for (int i = 0; i < locations.size(); i++) {
			ResourceLocation location = (ResourceLocation) locations.get(i);
			url = location.getResourceAsURL(ref);
			if (url != null) {
				return true;
			}
		}

		return false;
	}

	static interface ResourceLocation {
		public InputStream getResourceAsStream(String ref);

		public URL getResourceAsURL(String ref);
	}

	static class ClasspathLocation implements ResourceLocation {
		public URL getResourceAsURL(String ref) {
			String cpRef = ref.replace('\\', '/');
			return ResourceLoader.class.getClassLoader().getResource(cpRef);
		}

		public InputStream getResourceAsStream(String ref) {
			String cpRef = ref.replace('\\', '/');
			return ResourceLoader.class.getClassLoader().getResourceAsStream(cpRef);
		}
	}

	static class FileSystemLocation implements ResourceLocation {
		private File root;

		public FileSystemLocation(File root) {
			this.root = root;
		}

		public URL getResourceAsURL(String ref) {
			try {
				File file = new File(root, ref);
				if (!file.exists()) {
					file = new File(ref);
				}
				if (!file.exists()) {
					return null;
				}

				return file.toURI().toURL();
			} catch (IOException e) {
				return null;
			}
		}

		public InputStream getResourceAsStream(String ref) {
			try {
				File file = new File(root, ref);
				if (!file.exists()) {
					file = new File(ref);
				}
				return new FileInputStream(file);
			} catch (IOException e) {
				return null;
			}
		}

	}

}
